package com.wang.concurrency;

import java.util.Random;
import java.util.concurrent.ArrayBlockingQueue;
import java.util.concurrent.BlockingQueue;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.LinkedBlockingDeque;
import java.util.concurrent.SynchronousQueue;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.concurrent.TimeUnit;

public class ConsumerProducer {
	
	  private static final int CORE_POOL_SIZE = 5;
	    private static final int MAX_POOL_SIZE = 20;
	    private static final int KEEP_ALIVE_TIME = 20;
	    
	    

	public static void main(String[] args) {
		
		ExecutorService pool = getExecutorService();
		BlockingQueue<String> queue = getQueue();
		Producer producer = new Producer(queue, 100);
		Consumer consumer = new Consumer(queue, 100);
		pool.submit(producer);
		pool.submit(consumer);
		pool.submit(consumer);
		pool.shutdown();
		
	}
	 private static BlockingQueue<String> getQueue() {
	        return new ArrayBlockingQueue<>(10);
	 }
	
	 
	private static ExecutorService getExecutorService(){
		return new ThreadPoolExecutor(
				CORE_POOL_SIZE, MAX_POOL_SIZE, KEEP_ALIVE_TIME, TimeUnit.SECONDS,
				new LinkedBlockingDeque<Runnable>());
		
	}
	
	
	
	
	private static class Producer implements Runnable{
		
		
		private BlockingQueue<String > queue;
		private int count;
		
		public Producer(BlockingQueue<String> queue, int count) {
			super();
			this.queue = queue;
			this.count = count;
		}
		
		@Override
		public void run() {
			Random random = new Random();
			while(count-- >=0){
				try {
					Thread.sleep(100);					
					queue.put("produce:"+ random.nextInt(100) );
				} catch (InterruptedException e) {
					throw new RuntimeException(e);
				}
				
					
			}
			
		}
	}
	
	private static class Consumer implements Runnable{
		
		private BlockingQueue<String> queue;
		private int count;
		
		
		public Consumer(BlockingQueue<String> queue, int count) {
			super();
			this.queue = queue;
			this.count = count;
		}
		
		
		@Override
		public void run() {
			while(true){						
				try {			
					Thread.sleep(100);		
					String product = queue.take();					
					System.out.println(Thread.currentThread().getName() + " " + product);					
				} catch (InterruptedException e) {
					throw new RuntimeException(e);
				}
			}
			
		}
	}
	
	
	
	
	
	
	
	
	
	
	
	
	
	
	
	
	
	
	
	
}
